<?xml version="1.0" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>S3QL - Medium-level perl interface to the S3DB API</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<link rev="made" href="mailto:" />
</head>

<body style="background-color: white">

<p><a name="__index__"></a></p>
<!-- INDEX BEGIN -->

<ul>

	<li><a href="#name">NAME</a></li>
	<li><a href="#synopsis">SYNOPSIS</a></li>
	<li><a href="#description">DESCRIPTION</a></li>
	<ul>

		<li><a href="#select_queries">SELECT queries</a></li>
		<li><a href="#insert_queries">INSERT queries</a></li>
		<li><a href="#edit_queries">EDIT queries</a></li>
		<li><a href="#delete_queries">DELETE queries</a></li>
		<li><a href="#file_upload">File Upload</a></li>
	</ul>

	<li><a href="#see_also">SEE ALSO</a></li>
</ul>
<!-- INDEX END -->

<hr />
<p>
</p>
<h1><a name="name">NAME</a></h1>
<p>S3QL - Medium-level perl interface to the S3DB API</p>
<p>
</p>
<hr />
<h1><a name="synopsis">SYNOPSIS</a></h1>
<pre>
 <span class="keyword">require</span> <span class="variable">S3QL</span><span class="operator">;</span>
 <span class="variable">$s3q</span> <span class="operator">=</span> <span class="variable">new</span> <span class="variable">S3QL</span><span class="operator">;</span>
 <span class="variable">$s3q</span> <span class="operator">=</span> <span class="variable">new</span> <span class="variable">S3QL</span><span class="operator">(</span><span class="operator">{</span><span class="string">host</span> <span class="operator">=&gt;</span> <span class="variable">$host</span><span class="operator">,</span> <span class="string">key</span> <span class="operator">=&gt;</span> <span class="variable">$key</span><span class="operator">}</span><span class="operator">);</span>
</pre>
<pre>
 <span class="variable">$s3q</span><span class="operator">-&gt;</span><span class="keyword">select</span><span class="operator">(</span><span class="variable">$expression</span><span class="operator">,</span> <span class="variable">$table</span><span class="operator">,</span> <span class="operator">\</span><span class="variable">%criteria</span><span class="operator">);</span>
 <span class="variable">$string</span> <span class="operator">=</span> <span class="variable">$s3q</span><span class="operator">-&gt;</span><span class="variable">query</span><span class="operator">;</span>
 <span class="variable">$response</span> <span class="operator">=</span> <span class="variable">$s3q</span><span class="operator">-&gt;</span><span class="variable">submit</span><span class="operator">;</span>
</pre>
<pre>
 <span class="variable">$s3q</span><span class="operator">-&gt;</span><span class="variable">insert</span><span class="operator">(</span><span class="variable">$table</span><span class="operator">,</span> <span class="operator">\</span><span class="variable">%values</span><span class="operator">);</span>
 <span class="variable">$id</span> <span class="operator">=</span> <span class="variable">$s3q</span><span class="operator">-&gt;</span><span class="variable">commit</span><span class="operator">;</span>
</pre>
<pre>
 <span class="variable">$s3q</span><span class="operator">-&gt;</span><span class="variable">edit</span><span class="operator">(</span><span class="variable">$table</span><span class="operator">,</span> <span class="variable">$id</span><span class="operator">,</span> <span class="operator">\</span><span class="variable">%values</span><span class="operator">);</span>
 <span class="variable">$s3q</span><span class="operator">-&gt;</span><span class="variable">submit</span><span class="operator">;</span>
</pre>
<pre>
 <span class="variable">$s3q</span><span class="operator">-&gt;</span><span class="keyword">delete</span><span class="operator">(</span><span class="string">'project'</span><span class="operator">,</span> <span class="variable">$id</span><span class="operator">,</span> <span class="string">'yes'</span><span class="operator">);</span>
</pre>
<pre>
 <span class="variable">$s3q</span><span class="operator">-&gt;</span><span class="variable">uploadFile</span><span class="operator">(</span><span class="variable">$filename</span><span class="operator">,</span> <span class="variable">$resourceID</span><span class="operator">,</span> <span class="variable">$ruleID</span><span class="operator">);</span>
 <span class="variable">$id</span> <span class="operator">=</span> <span class="variable">$s3q</span><span class="operator">-&gt;</span><span class="variable">commit</span><span class="operator">;</span>
</pre>
<p>
</p>
<hr />
<h1><a name="description">DESCRIPTION</a></h1>
<p>This class provides a slightly higher-level interface to the S3DB API,
which is defined in terms of HTTP requests to an S3DB-aware web
server.  The low level interface is provided by the <a href="/S3QL/Raw.html">the S3QL::Raw manpage</a> class,
which itself is a fairly direct instantiation of the basic API.</p>
<p>The constructor requires the URI of an S3DB host along with a valid
key for that host. The default value uses the demonstration host
located at <code>http://ibl.mdanderson.org/s3dbdemo/</code> along with a key
that has been created for the user <code>guest</code>.  For the main deployment
at M.D. Anderson, you would get a valid key using the web interface
(as described at <a href="http://www.s3db.org">http://www.s3db.org</a>) and then specify</p>
<pre>
 <span class="keyword">my</span> <span class="variable">$s3q</span> <span class="operator">=</span> <span class="variable">new</span> <span class="variable">S3QL</span><span class="operator">(</span><span class="operator">{</span><span class="string">host</span> <span class="operator">=&gt;</span> <span class="string">'http://ibl.mdanderson.org/s3db'</span><span class="operator">,</span> <span class="variable">key</span> <span class="operator">=</span> <span class="variable">$mykey</span><span class="operator">}</span><span class="operator">)</span>
</pre>
<p>There are four kinds of statements: SELECT, INSERT, EDIT, and DELETE.</p>
<p>
</p>
<h2><a name="select_queries">SELECT queries</a></h2>
<p>This implementation is inspired by the DBI package.  That is, you must
first prepare the queries and later submit them to the database.  So,
a typical select query is created by</p>
<pre>
    <span class="keyword">require</span> <span class="variable">S3QL</span><span class="operator">;</span>
    <span class="variable">$s3q</span> <span class="operator">=</span> <span class="variable">new</span> <span class="variable">S3QL</span><span class="operator">;</span>
    <span class="variable">$s3q</span><span class="operator">-&gt;</span><span class="keyword">select</span><span class="operator">(</span><span class="string">'*'</span><span class="operator">,</span> <span class="string">'rules'</span><span class="operator">,</span> <span class="operator">{</span><span class="string">project_id</span> <span class="operator">=&gt;</span> <span class="number">111</span><span class="operator">}</span><span class="operator">);</span>
</pre>
<p>At this point, the query has been assembled and is ready to be sent to
the database. You can examine the current query (which is just a text
string that represents a URL appropriate for an HTTP GET request):</p>
<pre>
 <span class="keyword">print</span> <span class="variable">STDERR</span> <span class="variable">$s3q</span><span class="operator">-&gt;</span><span class="variable">query</span><span class="operator">;</span>
</pre>
<p>To actually execute the query, you must <code>submit</code> it.  Assuming
everything works correctly, the result is returned as a text string
that is equivalent to a table in tab-separated values format.  The
first line contains the column headers; each subsequent line contains
one query result, with the fields separated by tabs.</p>
<pre>
    <span class="variable">$response</span> <span class="operator">=</span> <span class="variable">$s3q</span><span class="operator">-&gt;</span><span class="variable">submit</span><span class="operator">;</span>
    <span class="variable">@line</span> <span class="operator">=</span> <span class="keyword">split</span> <span class="regex">/\n/</span><span class="operator">,</span> <span class="variable">$response</span><span class="operator">;</span>
    <span class="variable">@headline</span> <span class="operator">=</span> <span class="keyword">split</span> <span class="regex">/\t/</span><span class="operator">,</span> <span class="keyword">shift</span> <span class="variable">@line</span><span class="operator">;</span>
    <span class="keyword">for</span> <span class="variable">$item</span> <span class="operator">(</span><span class="variable">@line</span><span class="operator">)</span> <span class="operator">{</span>
       <span class="variable">@data</span> <span class="operator">=</span> <span class="keyword">split</span> <span class="regex">/\t/</span><span class="operator">,</span> <span class="variable">$item</span><span class="operator">;</span>
       <span class="comment"># do something with the data</span>
    <span class="operator">}</span>
</pre>
<p>The <code>submit</code> command uses the <em>LWP</em> package to make the necessary
HTTP requests.  It only tests for failure of the HTTP request itself
(for example, &quot;404 not found&quot; errors or timeout).  It is possible to
get back a valid HTML page that contains an error message from the
S3DB database.</p>
<p>
</p>
<h2><a name="insert_queries">INSERT queries</a></h2>
<p>To create new items in the database, you use an <code>insert</code> statement,
which must be <strong>committed</strong> rather than <strong>submitted</strong>.  The return value of
the <code>commit</code> command is the unique database ID assigned to the object
that you just created. In order to make statements about this object
(that is, to assign values to the properties associated with this
object), you must use this ID in a later <code>edit</code> command.</p>
<pre>
    <span class="variable">$s3q</span><span class="operator">-&gt;</span><span class="variable">insert</span><span class="operator">(</span><span class="string">'project'</span><span class="operator">,</span> <span class="operator">{</span><span class="string">project_name</span> <span class="operator">=&gt;</span> <span class="string">'Trial'</span><span class="operator">,</span>
                             <span class="string">project_description</span> <span class="operator">=&gt;</span> <span class="string">'My trial project'</span><span class="operator">}</span><span class="operator">);</span>
    <span class="variable">$id</span> <span class="operator">=</span> <span class="variable">$s3q</span><span class="operator">-&gt;</span><span class="variable">commit</span><span class="operator">;</span>
</pre>
<p>The <code>commit</code> command checks for several kinds of failures.  First, as
with the <code>submit</code> command, it checks that the HTTP request returned a
valid HTML page.  Next, it checks that the S3DB database reports a
successful insertion.  Finally, it checks that the return value
includes a database ID for the newly created object.  Failure of any
of these checks is passed back using the <code>croak</code> function in the <em>Carp</em>
package.</p>
<p>
</p>
<h2><a name="edit_queries">EDIT queries</a></h2>
<p>To edit the properties associated with a particular resource (item),
you need to know its ID in the database.  This ID is returned by a
successful <code>insert</code> statement.  It can also be found in the
<code>resource_id</code> column in the results of a successful <code>select</code>
statement.</p>
<pre>
    <span class="variable">$s3q</span><span class="operator">-&gt;</span><span class="variable">edit</span><span class="operator">(</span><span class="string">'project'</span><span class="operator">,</span> <span class="variable">$id</span><span class="operator">,</span> <span class="operator">{</span><span class="variable">project</span><span class="operator">-</span><span class="string">description</span> <span class="operator">=&gt;</span> <span class="string">"My really nifty trial project"</span><span class="operator">}</span><span class="operator">);</span>
    <span class="variable">$s3q</span><span class="operator">-&gt;</span><span class="variable">submit</span><span class="operator">;</span>
</pre>
<p>
</p>
<h2><a name="delete_queries">DELETE queries</a></h2>
<p>To delete an existing object, you must also know its database id.</p>
<pre>
    <span class="variable">$s3q</span><span class="operator">-&gt;</span><span class="keyword">delete</span><span class="operator">(</span><span class="string">'project'</span><span class="operator">,</span> <span class="variable">$id</span><span class="operator">,</span> <span class="string">'yes'</span><span class="operator">);</span>
</pre>
<p>The last argument is the value of the &quot;confirm&quot; entry required by the
API.  If you put anything other than &quot;yes&quot; here, then the object will
not get deleted (so it is not exactly clear to me why you would want
to call the function...).</p>
<p>
</p>
<h2><a name="file_upload">File Upload</a></h2>
<p>Finally, there is a special API for uploading files, which can be used
as the values of properties in the S3DB system.  As documented at
<a href="http://www.s3db.org">http://www.s3db.org</a>, file upload is a three-step process.</p>
<ol>
<li>
<p>Get a file key by making a call to the S3DB server.</p>
</li>
<li>
<p>Encode the file using base64 encoding, modified to replace all &quot;+&quot;
characters by the entity equivalent &quot;%2b&quot;. Use an HTTP GET or POST to
send the encoded data to the server.</p>
</li>
<li>
<p>Use an <code>insert</code> command to put information about the upload into the
'file&quot; table.</p>
</li>
</ol>
<p>Fortunately, we have wrapped all three steps into a single function.
You should, however, be alert to a danger that ensues from this
approach: really large files may fail partway through the upload, and
your only recourse is to start over.</p>
<p>The S3DB API allows you to break the file into fragments and send each
fragment separately, keeping track of how much gets through.  If you
want to do that, go read the API and figure out how to do it yourself.
That design grew out of their initial insistence on using HTTP GET
commands for file transfer, which limits the fragment size to the
number of characters that fit into a single URL.  The implementation
here relies on HTTP POST for the file transfer, and sends the file as
a single chunk.  This decision also puts nontrivial memory
requirements on the program that is uploading the file.  The entire
file is read into memory at once, and is base64-encoded in RAM.</p>
<p>With those caveats in mind, you can upload a file by providing a text
string containing the file name, numeric resource ID and rule ID
(which are needed to identify the resource that the file is to be
associated with, and the rule that makes the association), and
optional descriptive notes:</p>
<pre>
    <span class="variable">$s3q</span><span class="operator">-&gt;</span><span class="variable">uploadFile</span><span class="operator">(</span><span class="string">"filename"</span><span class="operator">,</span> <span class="variable">resourceID</span><span class="operator">,</span> <span class="variable">ruleID</span><span class="operator">,</span> <span class="string">"optional notes"</span><span class="operator">);</span>
    <span class="variable">$id</span> <span class="operator">=</span> <span class="variable">$s3q</span><span class="operator">-&gt;</span><span class="variable">commit</span><span class="operator">;</span>
</pre>
<p>An alternative form:</p>
<pre>
    <span class="variable">$s3q</span><span class="operator">-&gt;</span><span class="variable">uploadFile</span><span class="operator">(</span><span class="string">"filename"</span><span class="operator">,</span> <span class="variable">resourceID</span><span class="operator">,</span> <span class="variable">ruleID</span><span class="operator">,</span> <span class="string">"required notes"</span><span class="operator">,</span> <span class="variable">$fh</span><span class="operator">);</span>
</pre>
<p>allows you to pass in an open file handle instead of the name of an
actual file.  In this case, the &quot;filename&quot; string will be used as the name
of the file in the S3DB database, but the data will read from the handle.
Note that the method (rather unpolitely) closes the file handle when it
is finished with it.</p>
<p>The <code>uploadFile</code> command does check that</p>
<ol>
<li>
<p>the file exists and can be read</p>
</li>
<li>
<p>the file is nonempty</p>
</li>
<li>
<p>S3DB assigns a valid filekey to start the upload</p>
</li>
<li>
<p>S3DB reports that the file was transferred successfully</p>
</li>
</ol>
<p>The <code>uploadFile</code> command does <strong>not</strong> perform the final <code>insert</code> into
the 'file&quot; table.  As with the <code>insert</code> command, you must follow it
with a <code>commit</code> command to complete the operation.</p>
<p>
</p>
<hr />
<h1><a name="see_also">SEE ALSO</a></h1>
<p>The low level <a href="/S3QL/Raw.html">the S3QL::Raw manpage</a> package provides the direct interface to
S3DB; the high level <a href="/S3QL/Objects.html">the S3QL::Objects manpage</a> package provides a more
object-oriented view that may be better for some databases
constructed using S3DB.</p>

</body>

</html>
